package com.xy.biz.auth.service.impl;

import com.xy.biz.auth.domain.bo.UserLogStatusBO;
import com.xy.biz.auth.domain.bo.UserPasswordBO;
import com.xy.biz.auth.domain.req.GetTokenRequest;
import com.xy.biz.auth.domain.req.UserCodeLoginRequest;
import com.xy.biz.auth.domain.req.UserCodeRegisterRequest;
import com.xy.biz.auth.domain.utils.PasswordUtils;
import com.xy.biz.auth.manager.UserPasswordManager;
import com.xy.biz.auth.service.CaptchaService;
import com.xy.biz.auth.service.LogonService;
import com.xy.biz.auth.service.UserLogStatusService;
import com.xy.biz.uc.client.UserClient;
import com.xy.biz.uc.domain.dto.UserDTO;
import com.xy.biz.uc.domain.req.GetUserByUserCodeRequest;
import com.xy.biz.uc.domain.req.SaveUserRequest;
import com.xy.biz.uc.domain.resp.SaveUserResponse;
import com.xy.lang.domain.LongIdCodeName;
import com.xy.lang.domain.Result;
import com.xy.lang.exception.BadRequestException;
import com.xy.lang.util.ResultUtils;
import com.xy.tool.context.UserContext;
import com.xy.tool.jwt.TokenGenerator;
import com.xy.tool.util.BeanUtilsEx;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.Pbkdf2PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;

@Slf4j
@Service
public class LogonServiceImpl implements LogonService, InitializingBean {

    @Autowired
    private UserClient userClient;
    @Autowired
    private UserPasswordManager userPasswordManager;
    @Autowired
    private CaptchaService captchaService;
    @Autowired
    private UserLogStatusService userLogStatusService;
    @Autowired
    private TokenGenerator tokenGenerator;

    private Pbkdf2PasswordEncoder passwordEncoder;

    private final String INIT_PASSWORD = "123456";

    @Override
    public void afterPropertiesSet() throws Exception {
        passwordEncoder = new Pbkdf2PasswordEncoder();
        passwordEncoder.setAlgorithm(Pbkdf2PasswordEncoder.SecretKeyFactoryAlgorithm.PBKDF2WithHmacSHA512);
    }

    @Transactional
    @Override
    public Result<?> register(UserCodeRegisterRequest request) {
        Result<?> verifyCaptchaResult = captchaService.verifyCaptcha(request.getCaptchaId(), request.getCaptchaCode());
        if (verifyCaptchaResult.wasFailure()) {
            return verifyCaptchaResult;
        }
        SaveUserRequest saveUserRequest = BeanUtilsEx.copyProperties(request, () -> new SaveUserRequest());
        Result<SaveUserResponse> saveUserResult = userClient.saveUserByUserCode(saveUserRequest);
        if (saveUserResult.wasFailure()) {
            if (Result.CONFLICT.equals(saveUserResult.getCode())) {
                throw new BadRequestException();
            } else {
                return saveUserResult;
            }
        }
        SaveUserResponse saveUserResponse = saveUserResult.getData();

        UserPasswordBO userPasswordBO = UserPasswordBO.builder()
                .userId(saveUserResponse.getUserId())
                .password(passwordEncoder.encode(request.getPassword()))
                .updateTime(LocalDateTime.now())
                .build();
        userPasswordManager.saveUserPassword(userPasswordBO);

        return Result.success();
    }

    @Override
    public Result<String> login(UserCodeLoginRequest request) {
        Result<?> verifyCaptchaResult = captchaService.verifyCaptcha(request.getCaptchaId(), request.getCaptchaCode());
        if (verifyCaptchaResult.wasFailure()) {
            return Result.copy(verifyCaptchaResult);
        }
        UserDTO userDTO = ResultUtils.get(userClient.getUserByUserCode(
                GetUserByUserCodeRequest.builder()
                        .userCode(request.getUserCode())
                        .withUserGroup(true)
                        .build()));
        if (null == userDTO) {
            return Result.ofBadRequest("用户名不存在", request.getUserCode());
        }
        if (userDTO.getStatus() != 0) {
            return Result.ofBadRequest("用户处于禁闭状态，不可登录！", request.getUserCode() + "用户处于禁闭状态，不可登录！");
        }
        UserPasswordBO userPasswordBO = userPasswordManager.getUserPassword(userDTO.getUserId());
        if (!passwordEncoder.matches(request.getPassword(), userPasswordBO.getPassword())) {
            return Result.ofBadRequest("密码输入错误");
        }
        userLogStatusService.updateUserLogStatus(UserLogStatusBO.builder()
                .userId(userDTO.getUserId())
                .loginTime(LocalDateTime.now())
                .build());
        UserContext userContext = buildUserContext(userDTO);
        return Result.success(tokenGenerator.generateToken(24 * 60 * 60 * 1000, userContext));
    }

    @Override
    public Result<String> getToken(GetTokenRequest request) {
//        UserDTO userDTO = ResultUtils.get(userClient.getUserByUserCode(request.getUserCode()));
//        if(null == userDTO) {
//            return Result.ofNotFound("用户名不存在", request.getUserCode());
//        }
//        UserContext userContext = buildUserContext(userDTO);
//        return Result.success(tokenGenerator.generateToken(request.getExpiredSeconds() * 1000, userContext));
        return null;
    }

    @Override
    public Result<?> saveUser(SaveUserRequest request) {
        SaveUserRequest saveUserRequest = BeanUtilsEx.copyProperties(request, () -> new SaveUserRequest());
        Result<SaveUserResponse> saveUserResult = userClient.saveUserByUserCode(saveUserRequest);
        if (saveUserResult.wasFailure()) {
            if (Result.CONFLICT.equals(saveUserResult.getCode())) {
                throw new BadRequestException();
            } else {
                return saveUserResult;
            }
        }
        SaveUserResponse saveUserResponse = saveUserResult.getData();
        //随机生成定长8位密码
        //String passWord = PasswordUtils.generatePassWord(8);
        UserPasswordBO userPasswordBO = UserPasswordBO.builder()
                .userId(saveUserResponse.getUserId())
                .password(passwordEncoder.encode(INIT_PASSWORD))
                .updateTime(LocalDateTime.now())
                .build();
        userClient.updateUserBaseInfo(SaveUserRequest.builder().initialPassword(INIT_PASSWORD).userId(saveUserResponse.getUserId()).build());
        userPasswordManager.saveUserPassword(userPasswordBO);

        return Result.success();
    }

    private UserContext buildUserContext(UserDTO userDTO) {
        UserContext userContext = new UserContext();
        userContext.setTenantId(userDTO.getTenantId());
        userContext.setUserId(userDTO.getUserId());
        userContext.setUserName(userDTO.getUserName());
        LongIdCodeName userGroup = userDTO.getUserGroup();
        if (userGroup != null) {
            userContext.setUserGroupId(userGroup.getId());
            userContext.setUserGroupName(userGroup.getName());
            userContext.setUserGroupAbbr(userGroup.getAbbr());
        }
        return userContext;
    }

}
